package com.qianniu.napi.admin.web;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.google.common.base.Strings;
import com.qianniu.napi.admin.entity.*;
import com.qianniu.napi.admin.entity.penum.FantimeType;
import com.qianniu.napi.admin.entity.penum.IotypeEnum;
import com.qianniu.napi.admin.entity.penum.JftypeEnum;
import com.qianniu.napi.admin.entity.penum.XftypeEnum;
import com.qianniu.napi.admin.service.*;
import com.qianniu.napi.common.util.DateUtil;
import com.qianniu.napi.common.util.ObjectUtil;
import com.qianniu.napi.common.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 个人账务表
 * </p>
 *
 * @author chenxuebin
 * @since 2018-07-07
 */
@RestController
public class AccountController {

    private static final Logger logger = LoggerFactory.getLogger(AccountController.class);

    @Autowired
    private IUserService userService;
    @Autowired
    private IAccountService accountService;
    @Autowired
    private IAccountFlowService accountFlowService;
    @Autowired
    private IMaccountService maccountService;
    @Autowired
    private IFensService fensService;
    @Autowired
    private IJifenService jifenService;
    @Autowired
    private IJifenFlowService jifenFlowService;
    @Autowired
    private IXnbiService xnbiService;
    @Autowired
    private IFenxiaoService fenxiaoService;
    @Autowired
    private IFenxiaoFanService fenxiaoFanService;
    @Autowired
    private ICouponService couponService;
    @Autowired
    private IRedisService redisService;
    @Autowired
    private IMaccountFlowService maccountFlowService;
    @Autowired
    private IAccountTixianService accountTixianService;
    @Autowired
    private ISaccountService saccountService;

    @Autowired
    private IQnpay qnpay;

    /// / ************* bellow is bean interface for user *********

    @RequestMapping("/api/account/info")
    @ResponseBody
    public Jinfo accountInfo(String type) {
        Jinfo json = new Jinfo();
        Account bean = accountService.selectOne(
                new EntityWrapper<Account>().eq("uid", ObjectUtil.getUid()));
        if (bean == null) bean = initAccount();
        User u = userService.selectById(ObjectUtil.getUid());
        Map<String, Object> result = new HashMap<String, Object>();

        result.put("isMember", u.getIsMember());

        result.put("total", bean.getTotal());
        result.put("amount", bean.getAmount().add(bean.getMamount()));
        result.put("fanli", bean.getFanli());
        result.put("yajin", bean.getYajin());
        result.put("fanliing", bean.getFanliing());
        result.put("withdrawing", bean.getWithdrawing());
        if (!Strings.isNullOrEmpty(type) && type.equals("mima")) {
            result.put("mima", u.getPaypasswd());
        } else if (!Strings.isNullOrEmpty(type) && type.equals("yajin")) {
            result.clear();
            result.put("yajin", bean.getYajin());
        } else {
            Map<String, Object> fmap = fensService.selectMap(
                    new EntityWrapper<Fens>().setSqlSelect("count(1) total")
                            .eq("puid", ObjectUtil.getUid())
                            .eq("state", 1));
            Map<String, Object> nfmap = fensService.selectMap(
                    new EntityWrapper<Fens>().setSqlSelect("count(1) total")
                            .where("puid={0} and state=1 and  date_format(createtime, '%Y%m') = date_format(curdate() , '%Y%m')", ObjectUtil.getUid()));

            result.put("newfens", nfmap.get("total"));
            result.put("fens", fmap.get("total"));
        }

        json.setInfo(result);
        return json;
    }

    @RequestMapping("/api/account/add")
    @ResponseBody
    public JsonDO accountAdd(@Valid Account bean, BindingResult bindingResult, HttpServletRequest req) {
        JsonDO json = new JsonDO();

        bean.setCreatetime(new Date());
        bean.setMid(1L);
        bean.insert();
        return json;
    }


    @RequestMapping("/api/mch/jftxinfo")
    @ResponseBody
    public Jinfo jftxinfo(BigDecimal qian, HttpServletRequest req) {
        Jinfo json = new Jinfo();

        User user = redisService.getUser();
        Long mpid = ObjectUtil.getMpid();
        Long mid = ObjectUtil.getMid();
        Long uid = ObjectUtil.getUid();
        if (mpid == null || uid == null) {
            json.setCode(4);
            json.setMsg("参数有误");
            return json;
        }

        Jifen ujifen = jifenService.selectOne(new EntityWrapper<Jifen>().eq("uid", uid));
        BigDecimal jfnum = ujifen.getTotal();
        MerchantConfig mconfig = redisService.getMconfig();
        BigDecimal feilv = new BigDecimal(0);
        if (user.getIsMch() == 1) {
            FenxiaoFan fenxiaoFan = fenxiaoFanService.selectOne(new EntityWrapper<FenxiaoFan>()
                    .eq("mlevel", user.getMemberLevel())
                    .eq("hytype", 2)
                    .eq("mpid", mpid));
            feilv = fenxiaoService.getTxfei(user);
        }

        BigDecimal maxtx = jfnum.divide(new BigDecimal(mconfig.getJifenRate()));
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("jifen", jfnum);
        map.put("maxtx", maxtx.doubleValue());
        map.put("feilvName", feilv.doubleValue() == 0 ? "0" : feilv.multiply(new BigDecimal(100)).intValue() + "%");
        map.put("feilv", feilv.doubleValue());
        map.put("beilv", mconfig.getJifenRate());

        json.setInfo(map);
        return json;
    }

    @RequestMapping("/api/mch/tixian")
    @ResponseBody
    public Jinfo mchtixian(BigDecimal qian, HttpServletRequest req) {
        Jinfo json = new Jinfo();
        User user = redisService.getUser();
        if (qian == null || qian.doubleValue() < 0) {
            json.setCode(1);
            json.setMsg("参数有误");
            return json;
        }
        if (qian.doubleValue() < 1) {
            json.setCode(1);
            json.setMsg("最低1元起提现");
            return json;
        }
        if (user.getIsMch() != 1 && user.getIsPlatform() != 1) {
            json.setCode(1);
            json.setMsg("当前用户无权限操作");
            return json;
        }
        Long mpid = ObjectUtil.getMpid();
        Long mid = ObjectUtil.getMid();
        Long uid = ObjectUtil.getUid();

        // 计算费率
        BigDecimal feilv = new BigDecimal(0);
        if (user.getIsMch() == 1) {
            feilv = fenxiaoService.getTxfei(user);
        }

        // 计算扣除积分
        MerchantConfig mconfig = redisService.getMconfig();
        BigDecimal jifen = new BigDecimal(mconfig.getJifenRate()).multiply(qian);
        Jifen myjifen = jifenService.selectOne(new EntityWrapper<Jifen>().eq("uid", uid));
        if (jifen.doubleValue() > myjifen.getTotal().doubleValue()) {
            json.setCode(1);
            json.setMsg("当前用户积分不够");
            return json;
        }

        // 实际到账额
        BigDecimal money = qian.subtract(qian.multiply(feilv));


        // ******* 商家流水更新 *******
        MaccountFlow maf = new MaccountFlow();

        maf.setAmount(money);

        maf.setXftype(XftypeEnum.withdraw.getVal());
        maf.setIotype(IotypeEnum.output.getVal());// 系统默认秒提现
        maf.setIsConfirm(-1);
        maf.setTradetime(new Date());
        maf.setState(1);
        maf.setRemark("商家申请提现");
        maf.setCreatetime(new Date());
        maf.setMid(mid);
        maf.setMpid(mpid);
        maf.setUid(uid);
        maf.setSn(StringUtil.getSnNo("T"));// 实现不同业务类型的流水号

        String ip = ObjectUtil.getIP();

        // ******* 微信支付实时退款 *******
        Map<String, String> map = qnpay.payPakect(mpid, ObjectUtil.getAppid(), redisService.getUser(), money, "申请提现到零钱", ip);
        String return_code = map.get("return_code");
        String result_code = null;

        logger.debug(">>>payPakect map=" + JSON.toJSONString(map));
        if (("SUCCESS").equals(return_code)) {
            result_code = map.get("result_code");
            if (("SUCCESS").equals(result_code)) {
                //提现成功
                json.setCode(0);
                json.setMsg("提现成功");
                maf.setTransactionid(map.get("payment_no"));
                maf.insert();
                logger.debug(">>>withdrawApply OK and AccountFlow insert OK");
            } else {
                //提现失败
                json.setCode(1);
                json.setMsg(map.get("err_code_des"));
                return json;
            }
        }


        boolean flag = false;
        Maccount mact = maccountService.selectOne(new EntityWrapper<Maccount>().eq("mid", mid));
        Maccount mbean = new Maccount();//商家提现
        while (!flag) {

            Long version = mact.getVersion();
            BigDecimal total = mact.getTotal();
            BigDecimal amount = mact.getAmount();
            BigDecimal sale = mact.getSaleAmount();

            // ******* 待完善 商户账户余额不足的情况处理 *********
            mbean.setTotal(total.subtract(money));
            mbean.setSaleAmount(sale.subtract(money));
            mbean.setAmount(amount.subtract(money));

            mbean.setModifytime(new Date());
            mbean.setModifier(uid);
            mbean.setVersion(version + 1);

            maf.setIsConfirm(1);
            maf.setLasttotal(mact.getTotal());
            maf.setConfirmDate(new Date());
            maf.setModifytime(new Date());

            // ******* 更新账户表 ********
            flag = maccountService.update(mbean, new EntityWrapper<Maccount>().eq("mid", mid).eq("version", version));
            logger.debug(">>>withdrawApply maccountService.update flag=" + flag);
            if (!flag) mact = maccountService.selectOne(new EntityWrapper<Maccount>().eq("mid", mid));
            else maf.insertOrUpdate();
        }

        jifenService.addJifenFlow(uid, mid, mpid,
                jifen, true, FantimeType.now.getVal(),
                maf.getSn(), IotypeEnum.output, JftypeEnum.duihuan, "", null);

        return json;
    }

    @RequestMapping("/api/member/info")
    @ResponseBody
    public Jinfo memberInfo(HttpServletRequest req) {

        Jinfo info = new Jinfo();
        // 字段校验
        Long uid = ObjectUtil.getUid();
        Long mpid = ObjectUtil.getMpid();
        logger.info(">>>>>>>member/info uid=" + uid);
        User user = userService.selectById(uid);
        logger.info(">>>>>>>member/info user=", JSON.toJSONString(user));
        MerchantConfig mconfig = redisService.getMconfig();
        int qcout = couponService.selectCount(new EntityWrapper<Coupon>().eq("uid", uid).ne("is_used", 1).ne("is_outdate", 1));
        Jifen jifen = jifenService.selectOne(new EntityWrapper<Jifen>().eq("uid", uid));
        Xnbi xnbi = xnbiService.selectOne(new EntityWrapper<Xnbi>().eq("uid", uid));
        Account account = accountService.selectOne(new EntityWrapper<Account>().eq("uid", uid));
        Map map = new HashMap<String, Object>();
        if(user==null){
            info.setCode(1);
            info.setMsg("用户未授权登录");
            return info;
        }
        int mlevel = user.getMemberLevel();
        map.put("mima", user.getPaypasswd());
        map.put("zhekou", user.getDiscount());
        map.put("mlevel", mlevel);
        map.put("qcout", qcout);

        if (mconfig.getIsXnbi() == 1) {
            map.put("xnbi", xnbi != null ? xnbi.getTotal() : 0);
            map.put("isxnbi", 1);
        } else {
            map.put("jifen", jifen == null ? 0 : jifen.getTotal());
            map.put("jifenRate", mconfig.getJifenRate());
            map.put("isjifen", mconfig.getIsJifen() != null && mconfig.getIsJifen().intValue() == 1 ? 1 : 0);
        }

        if (account != null) {
            map.put("xiaofei", account.getChargeAmount());
            map.put("yue", account.getAmount().add(account.getMamount()));
        }

        logger.debug("=====================mlevel="+mlevel);

        if (mconfig.getIsFenxiao() == 1) {
            Fenxiao fenxiao = fenxiaoService.selectOne(new EntityWrapper<Fenxiao>().eq("mpid", mpid));
            logger.debug("============================fenxiao="+JSON.toJSONString(fenxiao));
            logger.debug("============================fenxiao.getHuifei1()="+fenxiao.getHuifei1());
            if (fenxiao != null) {
                map.put("huifei", mlevel == 1 ? fenxiao.getHuifei1() : mlevel == 2 ? fenxiao.getHuifei2() : mlevel == 3 ? fenxiao.getHuifei3() :
                        mlevel == 4 ? fenxiao.getHuifei4() : mlevel == 5 ? fenxiao.getHuifei5() : mlevel == 6 ? fenxiao.getHuifei6() : mlevel == 7 ? fenxiao.getHuifei7() : 0);
                map.put("hyname", mlevel == 1 ? fenxiao.getFxname1() : mlevel == 2 ? fenxiao.getFxname2() : mlevel == 3 ? fenxiao.getFxname3() :
                        mlevel == 4 ? fenxiao.getFxname4() : mlevel == 5 ? fenxiao.getFxname5() : mlevel == 6 ? fenxiao.getFxname6() : mlevel == 7 ? fenxiao.getFxname7() : "非会员");
                mlevel += 1;
                map.put("xiahuifei", mlevel == 1 ? fenxiao.getHuifei1() : mlevel == 2 ? fenxiao.getHuifei2() : mlevel == 3 ? fenxiao.getHuifei3() :
                        mlevel == 4 ? fenxiao.getHuifei4() : mlevel == 5 ? fenxiao.getHuifei5() : 0);

                if (account != null){
                    logger.debug("============map.get(xiahuifei)="+map.get("xiahuifei"));
                    logger.debug("============account.getChargeAmount()="+account.getChargeAmount());
                    map.put("chae", BigDecimal.valueOf(Double.parseDouble(map.containsKey("xiahuifei")&&map.get("xiahuifei")!=null?map.get("xiahuifei").toString():"0")).subtract(account.getChargeAmount()));
                }

            } else {
                map.put("hyname", "非会员");
            }
        }

        map.put("memberLevel", user.getMemberLevel() == null ? 0 : user.getMemberLevel());
        map.put("maurl", "http://img.qianniu010.com/vmall/ma.png");

        info.setInfo(map);
        return info;
    }

    //type 2:积分兑换提现
    @RequestMapping("/api/accout/withdraw/apply")
    @ResponseBody
    public Jinfo withdrawApply(@RequestParam("amount") BigDecimal money,
                               @RequestParam(value = "type", required = false) Integer type,
                               @RequestParam(value = "feilv", required = false) BigDecimal feilv,
                               HttpServletRequest req) {
        Jinfo json = new Jinfo();
        Long uid = ObjectUtil.getUid();
        Long mid = ObjectUtil.getMid();
        Long mpid = ObjectUtil.getMpid();

        Account act = accountService.selectOne(new EntityWrapper<Account>().eq("uid", uid));
        Maccount mact = maccountService.selectOne(new EntityWrapper<Maccount>().eq("mid", mid));

        if (act == null) act = initAccount();
        if (type != null && type == 2) {
            Jifen jifen = jifenService.selectOne(new EntityWrapper<Jifen>().setSqlSelect("total").eq("uid", uid));
            BigDecimal maxdui = feilv.multiply(jifen.getTotal());
            if (money.doubleValue() > maxdui.doubleValue()) {
                json.setCode(1);
                json.setMsg("提现额度超限");
                return json;
            }
        } else if (act.getAmount().doubleValue() < money.doubleValue()) {
            json.setCode(1);
            json.setMsg("余额不足");
            return json;
        }
        // ******* 系统默认秒提现 ******* 待完善 实现商家自定义配置


        // ******* 更新流水表 *******
        AccountFlow af = new AccountFlow();
        BigDecimal zero = new BigDecimal(0);

        af.setRealpay(money);
        af.setDikou(zero);
        af.setAmount(zero);
        af.setTotal(af.getRealpay().add(af.getAmount()).add(af.getDikou()));

        af.setXftype(XftypeEnum.withdraw.getVal());
        af.setIotype(IotypeEnum.output.getVal());// 系统默认秒提现

        af.setIsConfirm(-1);
        af.setTradetime(new Date());
        af.setState(1);
        af.setRemark("用户申请提现");
        af.setCreatetime(new Date());
        af.setMid(mid);
        af.setMpid(ObjectUtil.getMpid());
        af.setUid(uid);

        User user = redisService.getUser();
        af.setNickname(user != null ? user.getNickName() : null);
        af.setHeadimg(user != null ? user.getAvatarPic() : null);
        af.setPhone(user != null ? user.getPhone() : null);

        af.setSn(StringUtil.getSnNo("T"));// 实现不同业务类型的流水号

        // ******* 商家流水更新 *******
        MaccountFlow maf = new MaccountFlow();

        maf.setAmount(money);

        maf.setXftype(XftypeEnum.withdraw.getVal());
        maf.setIotype(IotypeEnum.output.getVal());// 系统默认秒提现
        maf.setIsConfirm(-1);
        maf.setTradetime(new Date());
        maf.setState(1);
        maf.setRemark("用户申请提现");
        maf.setCreatetime(new Date());
        maf.setMid(mid);
        maf.setMpid(af.getMpid());
        maf.setUid(uid);
        maf.setSn(af.getSn());// 实现不同业务类型的流水号

        String ip = ObjectUtil.getIP();

        // ******* 微信支付实时退款 *******

        Map<String, String> map = qnpay.payPakect(mpid, ObjectUtil.getAppid(), redisService.getUser(), money, "申请退款到零钱", ip);
        String return_code = map.get("return_code");
        String result_code = null;

        logger.debug(">>>payPakect map=" + JSON.toJSONString(map));
        if (("SUCCESS").equals(return_code)) {
            result_code = map.get("result_code");
            if (("SUCCESS").equals(result_code)) {
                //提现成功
                json.setCode(0);
                json.setMsg("提现成功");
                af.setLasttotal(act.getTotal());
                af.setLastamount(act.getAmount());
                af.insert();
                maf.insert();
                logger.debug(">>>withdrawApply OK and AccountFlow insert OK");
            } else {
                //提现失败
                json.setCode(1);
                json.setMsg(map.get("err_code_des"));
                return json;
            }
        }

        boolean flag = false;
        Account nbean = new Account();
        while (!flag && type != null && type != 2) {

            Long version = act.getVersion();
            BigDecimal amount = act.getAmount();
            BigDecimal total = act.getTotal();
            BigDecimal withdraw = act.getWithdraw();

            nbean.setAmount(amount.subtract(money));
            nbean.setTotal(total.subtract(money));
            nbean.setWithdraw(withdraw.add(money));
            nbean.setModifytime(new Date());
            nbean.setModifier(uid);
            nbean.setVersion(version + 1);

            af.setIsConfirm(1);
            af.setRuzhang(1);
            af.setLasttotal(act.getTotal());
            af.setLastamount(act.getAmount());
            af.setConfirmDate(new Date());

            // ******* 更新账户表 ********
            flag = accountService.update(nbean, new EntityWrapper<Account>().eq("uid", af.getUid()).eq("version", version));
            logger.debug(">>>withdrawApply accountService.update flag=" + flag);
            if (!flag) act = accountService.selectOne(new EntityWrapper<Account>().eq("uid", af.getUid()));
            else af.insertOrUpdate();
        }

        flag = false;
        Maccount mbean = new Maccount();//积分兑换提现
        while (!flag) {

            Long version = mact.getVersion();
            BigDecimal total = mact.getTotal();
            BigDecimal amount = mact.getAmount();
            BigDecimal sale = mact.getSaleAmount();

            // ******* 待完善 商户账户余额不足的情况处理 *********
//            if(money.doubleValue()> amount.doubleValue()){
//                json.setCode(1);
//                json.setInfo("当前余额不足");
//                return json;
//            }
            mbean.setTotal(total.subtract(money));
            mbean.setSaleAmount(sale.subtract(money));
            mbean.setAmount(amount.subtract(money));

            mbean.setModifytime(new Date());
            mbean.setModifier(uid);
            mbean.setVersion(version + 1);

            maf.setIsConfirm(1);
            maf.setLasttotal(mact.getTotal());
            maf.setConfirmDate(new Date());
            maf.setModifytime(new Date());

            // ******* 更新账户表 ********
            flag = maccountService.update(mbean, new EntityWrapper<Maccount>().eq("mid", mid).eq("version", version));
            logger.debug(">>>withdrawApply maccountService.update flag=" + flag);
            if (!flag) mact = maccountService.selectOne(new EntityWrapper<Maccount>().eq("mid", mid));
            else maf.insertOrUpdate();
        }

        return json;
    }

    // 积分兑换提现接口
    // /api/accout/withdraw/apply 单独剥离出积分提现接口
    @RequestMapping("/api/accout/jftixian")
    @ResponseBody
    public Jinfo jftixian(@RequestParam("amount") BigDecimal money,
                          @RequestParam(value = "jfcount", required = false) BigDecimal jfcount,
                          @RequestParam(value = "txtype", required = false) Integer txtype,
                          @RequestParam(value = "feilv", required = false) BigDecimal feilv) {
        Jinfo json = new Jinfo();
        Long uid = ObjectUtil.getUid();
        Long mid = ObjectUtil.getMid();
        Long mpid = ObjectUtil.getMpid();

        Account act = accountService.selectOne(new EntityWrapper<Account>().eq("uid", uid));
        Maccount mact = maccountService.selectOne(new EntityWrapper<Maccount>().eq("mid", mid));

        if (act == null) act = initAccount();
        Jifen jifen = jifenService.selectOne(new EntityWrapper<Jifen>().setSqlSelect("total").eq("uid", uid));
        BigDecimal maxdui = feilv.multiply(jifen.getTotal());
        if (jifen == null || jifen.getTotal().doubleValue() <= 0) {
            json.setCode(1);
            json.setMsg("积分不够");
            return json;
        }
        if (jfcount.doubleValue() > jifen.getTotal().doubleValue()) {
            json.setCode(1);
            json.setMsg("提现额度超限");
            return json;
        }
        if (txtype == null || txtype < 1 || txtype > 2) {
            json.setCode(4);
            json.setMsg("参数有误");
            return json;
        }
        String remark = txtype == 1 ? "用户申请线上积分兑换提现" : "用户申请线下积分兑换提现";
        Map<String, String> map = null;
        // ******* 系统默认秒提现 ******* 待完善 实现商家自定义配置
        AccountFlow af = new AccountFlow();
        if (txtype == 1) {
            // ******* 线上提现 更新流水表 *******

            BigDecimal zero = new BigDecimal(0);

            af.setRealpay(money);
            af.setDikou(zero);
            af.setAmount(zero);
            af.setTotal(af.getRealpay().add(af.getAmount()).add(af.getDikou()));

            af.setXftype(XftypeEnum.withdraw.getVal());
            af.setIotype(IotypeEnum.output.getVal());// 系统默认秒提现
            af.setOrigin("online");
            af.setIsConfirm(-1);
            af.setTradetime(new Date());
            af.setState(1);
            af.setRemark(remark);
            af.setCreatetime(new Date());
            af.setMid(mid);
            af.setMpid(ObjectUtil.getMpid());
            af.setUid(uid);

            User user = redisService.getUser();
            af.setNickname(user != null ? user.getNickName() : null);
            af.setHeadimg(user != null ? user.getAvatarPic() : null);
            af.setPhone(user != null ? user.getPhone() : null);

            af.setSn(StringUtil.getSnNo("T"));// 实现不同业务类型的流水号

            // ******* 商家流水更新 *******
            MaccountFlow maf = new MaccountFlow();

            maf.setAmount(money);

            maf.setXftype(XftypeEnum.withdraw.getVal());
            maf.setIotype(IotypeEnum.output.getVal());// 系统默认秒提现
            maf.setIsConfirm(-1);
            maf.setTradetime(new Date());
            maf.setState(1);
            maf.setRemark("用户申请提现");
            maf.setCreatetime(new Date());
            maf.setMid(mid);
            maf.setMpid(af.getMpid());
            maf.setUid(uid);
            maf.setSn(af.getSn());// 实现不同业务类型的流水号

            String ip = ObjectUtil.getIP();

            // ******* 微信支付实时退款 *******
            map = qnpay.payPakect(mpid, ObjectUtil.getAppid(), redisService.getUser(), money, "申请退款到零钱", ip);
            String return_code = map.get("return_code");
            String result_code = null;

            logger.debug(">>>payPakect map=" + JSON.toJSONString(map));
            if (("SUCCESS").equals(return_code)) {
                result_code = map.get("result_code");
                if (("SUCCESS").equals(result_code)) {
                    //提现成功
                    json.setCode(0);
                    json.setMsg("提现成功");

                    af.setTransactionid(map.get("payment_no"));
                    maf.setTransactionid(map.get("payment_no"));
                    af.setLasttotal(act.getTotal());
                    af.setLastamount(act.getAmount());
                    af.insert();
                    maf.insert();
                    logger.debug(">>>withdrawApply OK and AccountFlow insert OK");
                } else {
                    //提现失败
                    json.setCode(1);
                    json.setMsg(map.get("err_code_des"));
                    return json;
                }
            }

            boolean flag = false;
            Account nbean = new Account();
            while (!flag) {

                Long version = act.getVersion();
                BigDecimal amount = act.getAmount();
                BigDecimal total = act.getTotal();
                BigDecimal withdraw = act.getWithdraw();

                nbean.setAmount(amount.subtract(money));
                nbean.setTotal(total.subtract(money));
                nbean.setWithdraw(withdraw.add(money));
                nbean.setModifytime(new Date());
                nbean.setModifier(uid);
                nbean.setVersion(version + 1);

                af.setIsConfirm(1);
                af.setRuzhang(1);
                af.setLasttotal(act.getTotal());
                af.setLastamount(act.getAmount());
                af.setConfirmDate(new Date());
                af.setModifytime(new Date());

                // ******* 更新账户表 ********
                flag = accountService.update(nbean, new EntityWrapper<Account>().eq("uid", af.getUid()).eq("version", version));
                logger.debug(">>>withdrawApply accountService.update flag=" + flag);
                if (!flag) act = accountService.selectOne(new EntityWrapper<Account>().eq("uid", af.getUid()));
                else maf.insertOrUpdate();
            }

            flag = false;
            Maccount mbean = new Maccount();//积分兑换提现接口
            while (!flag) {

                Long version = mact.getVersion();
                BigDecimal total = mact.getTotal();
                BigDecimal amount = mact.getAmount();
                BigDecimal sale = mact.getSaleAmount();

                // ******* 待完善 商户账户余额不足的情况处理 *********

                mbean.setTotal(total.subtract(money));
                mbean.setSaleAmount(sale.subtract(money));
                mbean.setAmount(amount.subtract(money));

                mbean.setModifytime(new Date());
                mbean.setModifier(uid);
                mbean.setVersion(version + 1);

                // ******* 更新账户表 ********
                flag = maccountService.update(mbean, new EntityWrapper<Maccount>().eq("mid", mid).eq("version", version));
                logger.debug(">>>withdrawApply maccountService.update flag=" + flag);
                if (!flag) mact = maccountService.selectOne(new EntityWrapper<Maccount>().eq("mid", mid));
            }
            // 不管线下线上兑换，积分始终需要扣减
            jifenService.addJifenFlow(uid, mid, mpid,
                    jfcount, true, money,
                    txtype == 1 ? af.getSn() : StringUtil.getSnNo("TX"), IotypeEnum.output, JftypeEnum.duihuantx, "线上积分兑换提现", txtype == 1 ? af.getId() : 0l);
        } else {
            // 线下兑换，需要平台审核
            jifenService.addJifenFlowOffline(uid, mid, mpid,
                    jfcount, true, money,
                    txtype == 1 ? af.getSn() : StringUtil.getSnNo("TX"), IotypeEnum.output, JftypeEnum.duihuantx, "线下积分兑换提现", txtype == 1 ? af.getId() : 0l, true);

        }

        BigDecimal zero = new BigDecimal(0);
        if (txtype == 1) {
            // 线上兑换的积分，直接进入平台总账户
            maccountService.addMamountFlow(mid, zero, zero,
                    true, jfcount, af.getSn(), IotypeEnum.input, JftypeEnum.duihuan.getVal(), "商家用户积分兑换", txtype == 1 ? af.getId() : 0l, map.get("payment_no"));
        }

        return json;
    }

    // 现金提现接口
    // txtype 1:线上提现  2：线下提现
    // /api/accout/withdraw/apply 单独剥离出积分提现接口
    @RequestMapping("/api/accout/cashtixian")
    @ResponseBody
    public Jinfo cashtixian(@RequestParam("money") BigDecimal money,
                            @RequestParam("txtype") Integer txtype) {
        Jinfo json = new Jinfo();
        Long uid = ObjectUtil.getUid();
        Long mid = ObjectUtil.getMid();
        Long mpid = ObjectUtil.getMpid();
        //txtype=1:线上提现
        //txtype=2:线下提现
        if (money.doubleValue() < 0) {
            json.setCode(1);
            json.setMsg("提现金额有误");
            return json;
        }
        if (txtype == null || txtype < 1 || txtype > 2) {
            json.setCode(1);
            json.setMsg("提现参数有误");
            return json;
        }
        String remark = txtype == 1 ? "用户申请线上现金提现" : "用户申请线下现金提现";
        Account act = accountService.selectOne(new EntityWrapper<Account>().eq("uid", uid));
        Maccount mact = maccountService.selectOne(new EntityWrapper<Maccount>().eq("mid", mid));
        User user = redisService.getUser();
        AccountTixian tixian = new AccountTixian();

        tixian.setMoney(money);
        tixian.setStatus(1);//申请中
        tixian.setTxtype(txtype);
        tixian.setQtype(1);//现金提现
        tixian.setRemark(remark);
        tixian.setCreatetime(new Date());
        tixian.setMid(mid);
        tixian.setMpid(ObjectUtil.getMpid());
        tixian.setUid(uid);


        tixian.setNickname(user != null ? user.getNickName() : null);
        tixian.setHeadimg(user != null ? user.getAvatarPic() : null);
        tixian.setPhone(user != null ? user.getPhone() : null);
        tixian.setSn(StringUtil.getSnNo("T"));// 实现不同业务类型的流水号
        tixian.insert();

        if (act == null) act = initAccount();
        BigDecimal zero = new BigDecimal(0);

        // ******* 系统默认秒提现 *******
        // ====待完善 实现商家自定义配置
        AccountFlow af = new AccountFlow();
        af.setRealpay(money);
        af.setDikou(zero);
        af.setAmount(zero);
        af.setTotal(af.getRealpay());

        af.setXftype(XftypeEnum.withdraw.getVal());
        af.setIotype(IotypeEnum.output.getVal());// 系统默认秒提现
        af.setIsConfirm(-1);
        af.setState(1);
        af.setRemark(remark);
        af.setCreatetime(new Date());
        af.setTradetime(new Date());
        af.setMid(mid);
        af.setMpid(ObjectUtil.getMpid());
        af.setUid(uid);

        af.setNickname(user != null ? user.getNickName() : null);
        af.setHeadimg(user != null ? user.getAvatarPic() : null);
        af.setPhone(user != null ? user.getPhone() : null);
        af.setSn(tixian.getSn());// 实现不同业务类型的流水号

        Boolean flag = false;
        if (txtype == 1) {
            // ******* 更新流水表 *******

            // ******* 商家流水更新 *******
            String ip = ObjectUtil.getIP();

            // ******* 微信支付实时退款 *******
            Map<String, String> map = qnpay.payPakect(ObjectUtil.getMainmpid()!=null?ObjectUtil.getMainmpid():mpid,ObjectUtil.getAppid(), redisService.getUser(), money, "申请提现到零钱", ObjectUtil.getIP());
            String return_code = map.get("return_code");
            String result_code = null;

            logger.debug(">>>payPakect map=" + JSON.toJSONString(map));
            if (("SUCCESS").equals(return_code)) {
                result_code = map.get("result_code");
                if (("SUCCESS").equals(result_code)) {
                    //线上提现成功秒到
                    flag = true;
                    json.setCode(0);
                    json.setMsg("提现成功");
                    logger.debug(">>>>>>>>>>>>>>>>>>>>>withdrawApply OK and AccountFlow insert OK");
                    accountService.addAccountOutFlow(af);

                    MaccountFlow maf = new MaccountFlow();
                    maf.setAmount(money);
                    maf.setMamount(zero);
                    maf.setXftype(XftypeEnum.withdraw.getVal());
                    maf.setIotype(IotypeEnum.output.getVal());// 系统默认秒提现
                    maf.setIsConfirm(-1);
                    maf.setTradetime(new Date());
                    maf.setState(1);
                    maf.setRemark(remark);
                    maf.setCreatetime(new Date());
                    maf.setMid(mid);
                    maf.setMpid(af.getMpid());
                    maf.setUid(uid);
                    maf.setSn(af.getSn());// 实现不同业务类型的流水号
                    maccountService.addMaccountOutFlow(maf);

                    tixian.setStatus(2);//提现成功
                    tixian.setTradetime(new Date());//提现成功
                    tixian.updateById();

                } else {
                    //线上提现失败

                    json.setCode(1);
                    json.setMsg(map.get("err_code_des"));
                    return json;
                }
            }
        }

        if (!flag) {
            //--------线下提现，先提交审核--------
            af.setXftype(XftypeEnum.withdrawing.getVal());
            accountService.addAccountOutFlow(af);
        }

        return json;
    }

    // 积分兑换提现审核接口
    // ======待实现
    // /api/accout/withdraw/apply 单独剥离出积分提现接口
    @RequestMapping("/api/accout/jftxshenhe")
    @ResponseBody
    public Jinfo jftxshenhe(@RequestParam("state") Integer state,
                            @RequestParam("jid") Long id) {
        Jinfo json = new Jinfo();
        JifenFlow jf = jifenFlowService.selectById(id);
        BigDecimal zero = new BigDecimal(0);
        if (jf == null) {
            json.setCode(4);
            json.setMsg("参数有误");
            return json;
        }
        if (state != null && state == 1) {
            // 线下交易
            maccountService.addMamountFlow(jf.getMid(), zero, zero,
                    true, jf.getNum(), jf.getSn(), IotypeEnum.input, JftypeEnum.duihuan.getVal(), "用户积分兑换", id, "0");//代表线下

        } else if (state != null && state == -1) {
            JifenFlow jifenFlow = new JifenFlow();
            jifenFlow.setId(id);
            jifenFlow.setState(state);
            jifenFlow.updateById();
            //===待实现退回积分
            jifenService.addJifenFlow(jf.getUid(), jf.getMid(), jf.getMpid(),
                    jf.getNum(), true, zero,
                    jf.getSn(), IotypeEnum.input, JftypeEnum.refund, "积分兑换提现失败退回积分", id);
        }

        return json;
    }


    // 积分兑换提现审核接口
    // /api/accout/withdraw/apply 单独剥离出积分提现接口
    @RequestMapping("/api/accout/xjtxshenhe")
    @ResponseBody
    public Jinfo xjtxshenhe(@RequestParam("state") Integer state,
                            @RequestParam("jid") Long id) {
        Jinfo json = new Jinfo();
        AccountTixian tixian = accountTixianService.selectById(id);

        BigDecimal zero = new BigDecimal(0);
        if (tixian == null) {
            json.setCode(4);
            json.setMsg("参数有误");
            return json;
        }
        //当前用户
        BigDecimal money = tixian.getMoney();

        Long mid = tixian.getMid();
        Long uid = tixian.getUid();
        boolean flag = false;

        Account account = accountService.selectOne(new EntityWrapper<Account>().eq("uid", tixian.getUid()));
        Maccount mact = maccountService.selectOne(new EntityWrapper<Maccount>().eq("mid", tixian.getMid()));

        AccountFlow af = accountFlowService.selectOne(new EntityWrapper<AccountFlow>().eq("sn", tixian.getSn()));

        af.setId(null);
        af.setConfirmDate(null);
        af.setIsConfirm(-1);
        af.setCreatetime(new Date());

        if (state != null && state == 1) {

            if (tixian.getTxtype().intValue() == 1) {
                // 线上提现，审核通过
                Map<String, String> map = qnpay.payPakect(ObjectUtil.getMpid(), ObjectUtil.getAppid(), redisService.getUser(), money, "申请提现到零钱", ObjectUtil.getIP());
                String return_code = map.get("return_code");
                String result_code = null;

                Account nbean = new Account();

                logger.debug("-----------------------------payPakect map=" + JSON.toJSONString(map));
                if (("SUCCESS").equals(return_code)) {
                    result_code = map.get("result_code");
                    if (("SUCCESS").equals(result_code)) {
                        tixian.setTradetime(new Date());

                        af.setXftype(XftypeEnum.sendWithdrawing.getVal());
                        af.setRemark(XftypeEnum.sendWithdrawing.getName());
                        af.setIotype(IotypeEnum.output.getVal());
                        accountService.addAccountOutFlow(af);

                        MaccountFlow maf = new MaccountFlow();
                        maf.setAmount(money);
                        maf.setMamount(zero);
                        maf.setXftype(XftypeEnum.withdraw.getVal());
                        maf.setIotype(IotypeEnum.output.getVal());//系统默认秒提现
                        maf.setIsConfirm(-1);
                        maf.setTradetime(new Date());
                        maf.setState(1);
                        maf.setRemark(af.getRemark());
                        maf.setCreatetime(new Date());
                        maf.setMid(mid);
                        maf.setMpid(af.getMpid());
                        maf.setUid(uid);
                        maf.setSn(af.getSn());// 实现不同业务类型的流水号
                        maccountService.addMaccountOutFlow(maf);
                    } else {
                        json.setCode(1);
                        json.setMsg("营销账户余额不足");
                        return json;
                    }
                }
            } else {
                af.setXftype(XftypeEnum.sendWithdrawing.getVal());
                af.setRemark(XftypeEnum.sendWithdrawing.getName());
                af.setIotype(IotypeEnum.output.getVal());
                accountService.addAccountOutFlow(af);
            }

            tixian.setStatus(2);//通过
        } else if (state != null && state == -1) {

            af.setIotype(IotypeEnum.input.getVal());
            af.setXftype(XftypeEnum.refundWithdrawing.getVal());
            af.setRemark(XftypeEnum.refundWithdrawing.getName());
            accountService.addAccountInFlow(af);

            tixian.setStatus(3);//拒绝
        }

        // 更新流水
        tixian.setModifier(ObjectUtil.getUid());
        tixian.setModifytime(new Date());
        tixian.updateById();

        return json;
    }

    @RequestMapping("/api/account/modify")
    @ResponseBody
    public JsonDO accountUpdate(HttpServletRequest req,
                                Account act) {
        JsonDO json = new JsonDO();
        act.setModifytime(new Date());
        act.updateById();
        return json;
    }

    @RequestMapping("/api/account/detail")
    @ResponseBody
    public JsonDO getAccountDetailById(@RequestParam("token") String token,
                                       @RequestParam("id") long id, HttpServletRequest req
    ) {
        JsonDO json = new JsonDO();
        Account bean = accountService.selectById(id);
        json.setData(bean);
        return json;
    }

    private Account initAccount() {

        BigDecimal zero = new BigDecimal(0);
        Account bean = new Account();

        bean.setTotal(zero);
        bean.setAmount(zero);
        bean.setUnuseAmount(zero);
        bean.setFanli(zero);
        bean.setFanliing(zero);
        bean.setFreeze(zero);
        bean.setChargeAmount(zero);
        bean.setWithdraw(zero);
        bean.setMamount(zero);

        bean.setState(1);
        User user = redisService.getUser();
        bean.setNickname(user != null ? user.getNickName() : null);
        bean.setHeadimg(user != null ? user.getAvatarPic() : null);
        bean.setPhone(user != null ? user.getPhone() : null);

        bean.setUid(ObjectUtil.getUid());
        bean.setUid(ObjectUtil.getUid());
        bean.setMid(ObjectUtil.getMid());
        bean.setMpid(ObjectUtil.getMpid());
        bean.setPhone("");
        bean.setVersion(0l);
        bean.setCreatetime(new Date());
        logger.info(">>>>>>>>>>>initAccount user=", JSON.toJSONString(bean));
        bean.insert();

        return bean;
    }

    //我的押金
    @RequestMapping("/api/account/myyajin")
    @ResponseBody
    public Jinfo myyajin() {
        Jinfo info = new Jinfo();
        Account account = accountService.selectOne(new EntityWrapper<Account>().eq("uid", ObjectUtil.getUid()));
        if (account == null) {
            info.setCode(4);
            info.setMsg("押金账户不存在");
            return info;
        }
        AccountFlow accountFlow = accountFlowService.selectOne(new EntityWrapper<AccountFlow>()
                .eq("uid", ObjectUtil.getUid())
                .eq("xftype", XftypeEnum.jyajin.getVal()));

        Map map = new HashMap<String, Object>();
        map.put("yanji", account.getYajin());
        map.put("jytime", accountFlow == null ? "" : accountFlow.getConfirmDate());
        info.setInfo(map);
        return info;
    }

    //押金审核
    @RequestMapping("/api/account/yajinsh")
    @ResponseBody
    public Jinfo yajinsh(Long id, Integer status) {
        Jinfo info = new Jinfo();


        return info;
    }


    @RequestMapping("/api/account/lminfo")
    @ResponseBody
    public Jinfo accountlminfo(String type) {
        Jinfo json = new Jinfo();

        User ruser = redisService.getUser();
        Long uid = null;

        if (ruser.getIsAgent() == 1) uid = redisService.getLeagueAdminuser();
        else uid = ObjectUtil.getUid();

        Account bean = accountService.selectOne(
                new EntityWrapper<Account>().eq("uid", uid));

        if (bean == null) bean = initAccount();
        User u = userService.selectById(ObjectUtil.getUid());
        Map<String, Object> result = new HashMap<String, Object>();

        result.put("isMember", u.getIsMember());

        result.put("total", bean.getTotal());
        result.put("amount", bean.getAmount().add(bean.getMamount()));
        result.put("fanli", bean.getFanli());
        result.put("yajin", bean.getYajin());
        result.put("fanliing", bean.getFanliing());
        result.put("withdrawing", bean.getWithdrawing());
        if (!Strings.isNullOrEmpty(type) && type.equals("mima")) {
            result.put("mima", u.getPaypasswd());
        } else if (!Strings.isNullOrEmpty(type) && type.equals("yajin")) {
            result.clear();
            result.put("yajin", bean.getYajin());
        } else {
            Map<String, Object> fmap = fensService.selectMap(
                    new EntityWrapper<Fens>().setSqlSelect("count(1) total")
                            .eq("puid", ObjectUtil.getUid())
                            .eq("state", 1));
            Map<String, Object> nfmap = fensService.selectMap(
                    new EntityWrapper<Fens>().setSqlSelect("count(1) total")
                            .where("puid={0} and state=1 and  date_format(createtime, '%Y%m') = date_format(curdate() , '%Y%m')", ObjectUtil.getUid()));

            result.put("newfens", nfmap.get("total"));
            result.put("fens", fmap.get("total"));
        }

        json.setInfo(result);
        return json;
    }

    // 平台版多商家现金提现接口
    // 先默认秒到
    // ===后期再实现，大于5000需要审核===待实现
    @RequestMapping("/api/accout/pmchtixian")
    @ResponseBody
    public Jinfo pmchtixian(@RequestParam("money") BigDecimal money) {
        Jinfo json = new Jinfo();
        Long uid = ObjectUtil.getUid();
        Long mid = ObjectUtil.getMid();

        Long sid = ObjectUtil.getSid();

        if (uid == null) {
            json.setCode(1);
            json.setMsg("请授权登录之后再操作");
            return json;
        }
        if (money.doubleValue() <= 0) {
            json.setCode(1);
            json.setMsg("提现金额有误");
            return json;
        }
        if (sid == null) {
            json.setCode(1);
            json.setMsg("无权限操作");
            return json;
        }
        AccountTixian accountTixian = accountTixianService.
                selectOne(new EntityWrapper<AccountTixian>().eq("sid", sid));
        if (accountTixian != null) {
            json.setCode(1);
            json.setMsg("当日已申请提现过一次");
            return json;
        }

        String remark = "用户申请线上现金提现";

        Saccount sact = saccountService.selectOne(new EntityWrapper<Saccount>().eq("sid", sid));
        if (sact == null||sact.getAmount()==null) {
            json.setCode(1);
            json.setMsg("商家账户为空");
            return json;
        }
        if (sact.getAmount().doubleValue()<money.doubleValue()) {
            json.setCode(1);
            json.setMsg("余额不足");
            return json;
        }

        Maccount mact = maccountService.selectOne(new EntityWrapper<Maccount>().eq("mid", mid));

        User user = redisService.getUser();
        Store store = redisService.getStore(sid);
        AccountTixian tixian = new AccountTixian();
        Long mpid = user.getMpid();
        MerchantApp mapp = redisService.getMApp(mpid);

        tixian.setMoney(money);
        tixian.setStatus(1);//申请中
        tixian.setTxtype(1);
        tixian.setQtype(1);//现金提现
        tixian.setRemark(remark);
        tixian.setCreatetime(new Date());
        tixian.setMid(mid);
        tixian.setMpid(ObjectUtil.getMpid());
        tixian.setUid(uid);

        tixian.setNickname(user != null ? user.getNickName() : null);
        tixian.setHeadimg(user != null ? user.getAvatarPic() : null);
        tixian.setPhone(user != null ? user.getPhone() : null);
        tixian.setSn(StringUtil.getSnNo("T"));// 实现不同业务类型的流水号
        tixian.insert();

        BigDecimal zero = new BigDecimal(0);

        // ******* 系统默认秒提现 *******
        // ====待完善 实现商家自定义配置
        SaccountFlow saf = new SaccountFlow();
        saf.setTotal(money);
        saf.setAmount(money);
        saf.setYouhui(zero);
        saf.setMamount(zero);
        saf.setLasttotal(sact.getTotal());
        saf.setLastamount(sact.getAmount());

        saf.setXftype(XftypeEnum.withdraw.getVal());
        saf.setXftypename(XftypeEnum.withdraw.getName());

        saf.setIotype(IotypeEnum.output.getVal());// 系统默认秒提现
        saf.setRuzhang(-1);
        saf.setIsConfirm(-1);
        saf.setState(1);
        saf.setRemark(remark);
        saf.setCreateday(Integer.parseInt(DateUtil.getToday("YYYYMMdd")));
        saf.setCreatetime(new Date());
        saf.setTradetime(new Date());

        saf.setMid(mid);
        saf.setMpid(ObjectUtil.getMpid());
        saf.setUid(uid);
        saf.setSid(sid);
        saf.setLeagueid(store.getLeagueid());

        saf.setSn(tixian.getSn());// 实现不同业务类型的流水号

        Boolean flag = false;

        // ******* 更新流水表 *******

        // ******* 商家流水更新 *******
        String ip = ObjectUtil.getIP();

        // ******* 微信支付实时退款 *******
        Map<String, String> map = qnpay.payPakect(mpid, mapp.getAppid(), user, money, "申请提现到零钱", ObjectUtil.getIP());
        String return_code = map.get("return_code");
        String result_code = null;

        logger.debug(">>>payPakect map=" + JSON.toJSONString(map));
        if (("SUCCESS").equals(return_code)) {
            result_code = map.get("result_code");
            if (("SUCCESS").equals(result_code)) {
                //线上提现成功秒到
                flag = true;
                json.setCode(0);
                json.setMsg("提现成功");
                logger.debug("------------------------pmchtixian OK and AccountFlow insert OK");

                saf.setTransactionid(map.get("payment_no"));

                saccountService.addSaccountOutFlow(saf);

                MaccountFlow maf = new MaccountFlow();
                maf.setAmount(money);
                maf.setMamount(zero);
                maf.setXftype(XftypeEnum.withdraw.getVal());
                maf.setIotype(IotypeEnum.output.getVal());// 系统默认秒提现
                maf.setIsConfirm(-1);
                maf.setTradetime(new Date());
                maf.setState(1);
                maf.setRemark(remark);
                maf.setCreatetime(new Date());
                maf.setMid(mid);
                maf.setMpid(saf.getMpid());
                maf.setUid(uid);
                maf.setSn(saf.getSn());// 实现不同业务类型的流水号
                maf.setTransactionid(saf.getTransactionid());// 实现不同业务类型的流水号
                maccountService.addMaccountOutFlow(maf);

                tixian.setStatus(2);//提现成功
                tixian.setTradetime(new Date());//提现成功
                tixian.updateById();

            } else {
                //线上提现失败
                json.setCode(1);
                json.setMsg(map.get("err_code_des"));
                return json;
            }
        }

        if (!flag) {
            //--------如果提现失败，线下提现，先提交审核--------
            saf.setXftype(XftypeEnum.withdrawing.getVal());
            //先冻结
            saccountService.addSaccountOutFlow(saf);
        }

        return json;
    }

}
